package codeCreate.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSON;

import codeCreate.domain.Country;
import codeCreate.util.TextAnalysis.ApplyCreateController;
import codeCreate.util.TextAnalysis.ControllerAnalysis;
import codeCreate.util.TextAnalysis.DeviceCommonController;
import codeCreate.util.annotation.resolve.BeanAnnotationResolve;

/**
 * 
* 项目名称:  工具项目
* 包:        codeCreate.util 
* 类名称:    ControllerResolveUtil.java
* 类描述:    解析springmvc模式中控制器的信息
* 创建人:    fw  
* 创建时间:  2017年5月8日 上午11:27:17
 */
public class ControllerResolveUtil {
    private Class<?>[] controllerClass;
    private String controller_path = "controllerPath";
    private String methods_info = "methodsInfo";
    private String method_introduction = "methodIntroduction";
    private String request_type = "requestType";
    private String response_type = "responseType";
    private String controller_introduction = "controllerIntroduction";

    public ControllerResolveUtil(Class<?>[] controllerClass) {
        this.controllerClass = controllerClass;
    }

    public Map<Class<?>, Map<String, Object>> textAnnotationResolve() {
        Map<Class<?>, Map<String, Object>> annotationMap = resolve();
        for (Class<?> clazz : controllerClass) {
            Map<String, Object> controllerMap = (Map<String, Object>) annotationMap.get(clazz);
            @SuppressWarnings("unchecked")
            Map<String, Object> methodsMap = (Map<String, Object>) controllerMap.get(methods_info);
            Set<String> methodPathSet = methodsMap.keySet();
            String[] methodPaths = new String[methodPathSet.size()];
            methodPathSet.toArray(methodPaths);
            ControllerAnalysis controllerAnalysis = new ControllerAnalysis(clazz, methodPaths);
            Map<String, Object> analyzedMap = controllerAnalysis.analyze();
            Iterator<Entry<String, Object>> iterator = analyzedMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> entry = iterator.next();
                if (entry.getValue() instanceof Map<?, ?>) {
                    methodsMap.put(entry.getKey(), entry.getValue());
                }
            }
            controllerMap.put(controller_introduction, analyzedMap.get(controller_introduction));
            analyzedMap.put(controller_introduction, null);
        }
        return annotationMap;
    }

    /**
     * 利用注解解析controller类信息
     * 返回一个包含多个controller类信息的map，最外层区分不同controller类，
     * 第二层map包含类信息，其中方法信息用methodsInfo关键字存在第二层map中的，
     * 第三层map为每一个方法的具体信息，格式为：
     * {
    "codeCreate.util.TextAnalysis.DeviceCommonController": {
        "controllerPath": "/common",
        "methodsInfo": {
            "methodPath": {}
        }
    },
    "codeCreate.util.TextAnalysis.ApplyCreateController": {
        "controllerPath": "/DeviceService/apply",
        "methodsInfo": {
            "methodPath": {}
        }
    }
    }
    * @return
     */
    public Map<Class<?>, Map<String, Object>> resolve() {
        Map<Class<?>, Map<String, Object>> map = null;
        for (Class<?> controllerClass : controllerClass) {
            Controller controller = controllerClass.getAnnotation(Controller.class);
            RequestMapping controllerRequestMapping = controllerClass.getAnnotation(RequestMapping.class);
            if (controller == null || controllerRequestMapping == null) {
                break;
            }
            String controllerPath = controllerRequestMapping.value()[0];
            Map<String, Map<String, Object>> methodMaps = methodsInfoResolve(controllerClass);
            if (methodMaps != null) {
                Map<String, Object> controllerInfoMap = new HashMap<>();// 单个类的map
                controllerInfoMap.put(controller_path, controllerPath);// 类路径
                controllerInfoMap.put(controller_introduction, controllerIntroductionResolve(controllerClass));
                controllerInfoMap.put(methods_info, methodMaps);// 类中方法map
                if (map == null) {
                    map = new HashMap<>();
                }
                map.put(controllerClass, controllerInfoMap);
            }
        }
        System.out.println(JSON.toJSONString(map));
        return map;
    }

    private String controllerIntroductionResolve(Class<?> clazz) {
        codeCreate.util.annotation.type.Controller controller = clazz
                .getAnnotation(codeCreate.util.annotation.type.Controller.class);
        if (controller != null) {
            return controller.introduction();
        }
        return "";
    }

    private Map<String, Map<String, Object>> methodsInfoResolve(Class<?> clazz) {
        Map<String, Map<String, Object>> methodsMap = null;
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
            if (requestMapping == null) {
                continue;
            }
            if (methodsMap == null) {
                methodsMap = new HashMap<>();
            }
            String methodPath = StringUtils.isEmpty(requestMapping.value()[0]) ? "" : requestMapping.value()[0];
            Map<String, Object> methodInfoMap = new HashMap<>();
            codeCreate.util.annotation.type.Method methodAnnotation = method
                    .getAnnotation(codeCreate.util.annotation.type.Method.class);
            if (methodAnnotation != null) {
                methodInfoMap.put(request_type, methodAnnotation.requestType());
                methodInfoMap.put(response_type, methodAnnotation.responseType());
                methodInfoMap.put(method_introduction, methodAnnotation.introduction());
                methodsMap.put(methodPath, methodInfoMap);
            }
        }
        return methodsMap;
    }

    public List<Map<String, Object>> beanInfoResolve(Class<?> clazz) {
        return BeanAnnotationResolve.resolve(clazz);
    }

    public List<String[]> resolveBeanMapList2Array(Class<?> clazz, String[] template) {
        return BeanAnnotationResolve.resolveBeanMapList2Array(beanInfoResolve(clazz), null, template);
    }

    public static void main(String[] args) {
        Class<?>[] clazz = { DeviceCommonController.class, ApplyCreateController.class };
        ControllerResolveUtil controllerResolveUtil = new ControllerResolveUtil(clazz);
        // controllerResolveUtil.resolve();
        String name = "name";
        String is_null = "isNull";
        String field_name = "fieldName";
        String length = "length";
        String introduction = "introduction";
        String field_type = "fieldType";
        String[] requestTemplate = { field_name, is_null, field_type, length, name, introduction };
        System.out.println(
                JSON.toJSONString(controllerResolveUtil.resolveBeanMapList2Array(Country.class, requestTemplate)));
    }
}
